package wili.attrMapping._user.b1.exp;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Predicate;

import wili.c.Ca;
import wili.c.reg.GramarNode;
import wili.c.reg.MatchRet;
import wili.logic.GramarNode_jsonExp;

/**
 * Exp without and or operator.
 * 
 * @author weila 2022年10月4日
 */
public abstract class MathExpB1 {
	public boolean isNot = false;
	public final int id = ++GenID;
	{
		if (id == 3)
			Ca.pause();
	}

	/**
	 * 在源串中的部分, if null, toString() must use other way.
	 */
	public String expSt;

	public VarOrValueb1 ll, rr;// for cpExp.

	public String op = "";// for cpExp.

	public abstract String getString(int refresh);

	public static MathExpB1 newInst(String st) {
		// ['15','16'].includes(${ObjType})
		GramarNode gm = new GramarNode_jsonExp().get();
		gm.print(-11);
		MatchRet nod = gm.read(st, 0);
		if (nod == null) {
			throw Ca.newRuntimeException(gm.name + ", grammar error:" + st);
		}
		return expOf(nod);
	}

	public List<Varb1> findVarList(String name, List<Varb1> toList) {
		Predicate<MathExpB1> pred = new Predicate<MathExpB1>() {
			@Override
			public boolean test(MathExpB1 exp) {
				if (exp instanceof Varb1) {
					Varb1 va = (Varb1) exp;
					if (name.isEmpty() || va.name.equals(name)) {
						toList.add(va);
					}
				}
				return false;
			}
		};
		traverse(pred);
		return toList;
	}

	public abstract void traverse(Predicate<MathExpB1> pred);

	public static MathExpB1 expOf(MatchRet nod) {
		switch (nod.name) {
		case "cp":
			return new Cpb1(nod);
		case "fun":
			return new Funb1(nod);
		case "var":
			return new Varb1(nod);
		case "value":
			return new Valueb1(nod);
		case "lr":
			return new LrExp(nod);
		default:
			Ca.asert(false, nod);
			return null;
		}
	}

	public int valueAsInt() {
		Integer ret = this.value();
		return ret;
	}

	public void collectVarNameToValuesMap(Map<String, Set<Object>> map) {
	}

	public static class PredicateObj implements Predicate<MathExpB1> {
		public final Map<String, Set<Object>> valuesMap;

		public PredicateObj(Map<String, Set<Object>> valuesMap) {
			this.valuesMap = valuesMap;
		}

		public static final Predicate<MathExpB1> Collect_nameToValuesMap = new Predicate<MathExpB1>() {
			@Override
			public boolean test(MathExpB1 exp) {
				return false;
			}
		};

		@Override
		public boolean test(MathExpB1 t) {
			if (valuesMap != null) {
				return Collect_nameToValuesMap.test(t);
			} else {
				return false;
			}
		}
	}

	public Cpb1 toCpExp() {
		return (Cpb1) this;
	}

	public Varb1 toVar() {
		return (Varb1) this;
	}

	public Valueb1 toValue() {
		return (Valueb1) this;
	}

	public abstract <T> T value();

	public static boolean isEqualsList(List<MathExpB1> aa, List<MathExpB1> bb) {
		if (aa.size() != bb.size())
			return false;
		for (int i = 0; i < aa.size(); i++) {
			MathExpB1 son = aa.get(i), son2 = bb.get(i);
			if (!son.equals(son2))
				return false;
		}
		return true;
	}

	public abstract Boolean isTrue();

	static int GenID;
}
